package guida.ccf.gzuexaminesystem.exception;

import guida.ccf.gzuexaminesystem.common.ResponseResult;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;

@ControllerAdvice
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {

    /**
     * 登录失败异常
     */
    @ExceptionHandler(CustomLoginException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, CustomLoginException e){
        log.error("CustomLoginException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        log.error(e.getCode() + "");
        return ResponseResult.fail(e.getMessage(), e.getCode());
    }


    /**
     *  Token 认证异常
     */
    @ExceptionHandler(CustomTokenException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, CustomTokenException e){
        log.error("CustomTokenException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage(), e.getCode());
    }

    /**
     * SpringSecurity 内部认证错误
     */
    @ExceptionHandler(InternalAuthenticationServiceException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, InternalAuthenticationServiceException e){
        log.error("InternalAuthenticationServiceException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage(), 401);
    }



    /**
     * jwt 解析异常 SignatureException
     */
    @ExceptionHandler(SignatureException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, SignatureException e){
        log.error("SignatureException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage());
    }


    /**
     * fastJson 解析异常
     */
    @ExceptionHandler(java.lang.ClassCastException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, java.lang.ClassCastException e) {
        log.error("ClassCastException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage());
    }


    /**
     *  拦截校验属性不符合要求的时候的异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseResult<?> MethodArgumentNotValidExceptionHandler(HttpServletRequest request,
                                                                    MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String defaultMessage = fieldErrors.get(0).getDefaultMessage();
        log.error("MethodArgumentNotValidException 错误原因为 [{}]，请求路径 [{}]",
                defaultMessage, request.getRequestURI());
        return ResponseResult.fail(defaultMessage);

    }

    /**
     *  数据库完整性约束异常
     */
    @ExceptionHandler(value = SQLIntegrityConstraintViolationException.class)
    public ResponseResult<?> MethodArgumentNotValidExceptionHandler(HttpServletRequest request,
                                                                    SQLIntegrityConstraintViolationException e) {
        log.error("SignatureException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage());

    }

    /**
     * 运行时异常处理 RuntimeException
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, RuntimeException e) {
        log.error("RuntimeException 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage());
    }



    /**
     * 系统保底异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseResult<?> exceptionHandler(HttpServletRequest request, Exception e) {
        log.error("Exception 错误原因为: " + e.getMessage());
        log.error("Exception 错误原因为 [{}]，请求路径 [{}]",
                e.getMessage(), request.getRequestURI());
        return ResponseResult.fail(e.getMessage());
    }

}
